#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <climits>

using namespace std;

struct ListNode
{
    int val;
    ListNode *next;
    ListNode() : val(0), next(nullptr) {}
    ListNode(int x) : val(x), next(nullptr) {}
    ListNode(int x, ListNode *next) : val(x), next(next) {}
};

// 环形链表
class Solution
{
public:
    bool hasCycle(ListNode *head)
    {

        if (head == nullptr || head->next == nullptr)
        {
            return false;
        }
        unordered_set<ListNode *> hash;
        while (head)
        {
            if (hash.count(head))
                return true;
            hash.insert(head);
            head = head->next;
        }
        return false;
    }
};

// 环形链表II
class Solution
{
public:
    ListNode *detectCycle(ListNode *head)
    {
        if (head == nullptr || head->next == nullptr)
        {
            return nullptr;
        }
        unordered_set<ListNode *> hash;
        while (head)
        {
            if (hash.count(head))
                return head;
            hash.insert(head);
            head = head->next;
        }
        return nullptr;
    }
};

// 合并两个有序链表
class Solution
{
public:
    ListNode *mergeTwoLists(ListNode *list1, ListNode *list2)
    {
        ListNode *newhead = new ListNode();
        ListNode *tail = newhead;
        while (list1 && list2)
        {
            if (list1->val <= list2->val)
            {
                tail->next = list1;
                list1 = list1->next;
            }
            else
            {
                tail->next = list2;
                list2 = list2->next;
            }
            tail = tail->next;
        }
        if (list1)
        {
            tail->next = list1;
        }
        if (list2)
        {
            tail->next = list2;
        }

        return newhead->next;
    }
};

// 两数相加
class Solution
{
public:
    ListNode *addTwoNumbers(ListNode *l1, ListNode *l2)
    {
        ListNode *newhead = new ListNode();
        ListNode *tail = newhead;
        int carry = 0;
        while (l1 || l2 || carry)
        {
            int sum = 0;
            if (l1)
            {
                sum += l1->val;
                l1 = l1->next;
            }
            if (l2)
            {
                sum += l2->val;
                l2 = l2->next;
            }
            sum += carry;
            ListNode *node = new ListNode(sum % 10);
            tail->next = node;
            tail = tail->next;
            carry = sum / 10;
        }
        return newhead->next;
    }
};

// 删除链表倒数第N个节点
class Solution
{
public:
    ListNode *removeNthFromEnd(ListNode *head, int n)
    {
        int count = 0;
        ListNode *cur = head;
        while (cur)
        {
            count++;
            cur = cur->next;
        }
        cur = head;
        if (count == n)
            return head->next;
        for (int i = 0; i < count - n - 1; i++)
        {
            cur = cur->next;
        }
        cur->next = cur->next->next;
        return head;
    }
};